﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "IUserTransaction.h"
#include "MoveWindowDoorAction.h"
#include "IElementShapeHandle.h"
#include "UiCommonDialog.h"
#include "MoveUtils.h"
#include "IUiView.h"
#include "IUiDocument.h"
#include "IGeometry.h"
#include "IDocument.h"
#include "IInstance.h"
#include "IRegenerator.h"
#include "UiTransactionErrorProcessor.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace ggp;
namespace gcmp
{
    MoveWindowDoorAction::MoveWindowDoorAction()
    {
    }

    MoveWindowDoorAction::MoveWindowDoorAction(const ElementId& id, const Vector3d& startPt)
        : m_toBeMoveElementId(id)
        , m_startPt(startPt)
    {

    }

    MoveWindowDoorAction::MoveWindowDoorAction(const ElementId& id)
        : m_toBeMoveElementId(id)
    {

    }

    MoveWindowDoorAction::~MoveWindowDoorAction()
    {

    }

    void MoveWindowDoorAction::InitAction( gcmp::IUiView* pCurrentView )
    {
        IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
        IDocument* pDoc = pUiDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"文档为空",L"GDMPLab",L"2024-03-30");
        IElementShapeHandle* pGrip = quick_cast<IElementShapeHandle>(pDoc->GetElement(m_toBeMoveElementId));
        if (pGrip)
        {
            m_startPt = pGrip->GetPosition();
        }
    }

    bool MoveWindowDoorAction::OnLButtonUp( IUiView* pCurrentView, const gcmp::Vector3d& pos )
    {
        if (m_upUserTransaction != nullptr && m_upUserTransaction->IsStarted())
        {
            m_upUserTransaction->Commit();
        }
        UpdateView();
        MarkFinishStatus(ActionFinishStatus::Successful);
        return true;
    }

    bool MoveWindowDoorAction::OnMovePoint(IUiView* pCurrentView,const gcmp::Vector3d& pos)
    {
        IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
        DBG_WARN_AND_RETURN_UNLESS(pUiDoc, false, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
        IDocument* pDoc = pUiDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_UNLESS(pDoc, false, L"文档为空",L"GDMPLab",L"2024-03-30");

        Vector3d posOnWorkPlane;
        ActionBase::ProjectPositionOnWorkPlane(pCurrentView, pos, posOnWorkPlane);
        Vector3d endPt = posOnWorkPlane;
        IElement* pElement = pDoc->GetElement(m_toBeMoveElementId);
        bool isOk = false;
        if (IsA<IInstance>(pElement))
        {
            if (m_upUserTransaction == nullptr)
            {
                m_upUserTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"移动"), false);
                DBG_WARN_AND_RETURN_UNLESS(m_upUserTransaction, false, L"m_upUserTransaction为空",L"GDMPLab",L"2024-03-30");
            }
            if (m_upUserTransaction->IsStarted())
            {
                m_upUserTransaction->Rollback();
            }
            m_upUserTransaction->Start();
            Vector3d moveDir = endPt- m_startPt;
            MoveUtils::MoveElement(pElement, moveDir);
            isOk = pDoc->GetRegenerator()->RegenerateDocument();
        }
        //else if (IsA<AuxiliaryElement>(pElement) || IsA<IElementShapeHandle>(pElement))
        // 此从PickActionBase继承就会获得判断AuxiliaryElement的能力，目前从ActionBase继承不行。
        else if (IsA<IElementShapeHandle>(pElement))
        {
            //移动临时对象时，会直接修改真正的对象，所以要启动事务。
            if (m_upUserTransaction == nullptr)
            {
                m_upUserTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"移动"), false);
                DBG_WARN_AND_RETURN_UNLESS(m_upUserTransaction, false, L"m_upUserTransaction为空",L"GDMPLab",L"2024-03-30");
            }
            if (m_upUserTransaction->IsStarted())
            {
                m_upUserTransaction->Rollback();
                //临时对象一般是跟着一般对象走的，当一般对象Rollback时，更新临时对象
                std::vector<ElementId> elementIds(1, pElement->GetElementId());
                pDoc->GetRegenerator()->ForceRegeneratingElements(elementIds);
            }
            m_upUserTransaction->Start();
            gcmp::Vector3d moveDir = endPt - m_startPt;
            MoveUtils::MoveElement(pElement, moveDir);
            isOk = pDoc->GetRegenerator()->RegenerateDocument();
        }
        UpdateView();
        if(!isOk)
        {
            UiTransactionErrorProcessor::ProcessLastError(m_upUserTransaction.get());
        }

        return true;
    }
}
